﻿// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

namespace StyleMVVM.Controls.Common
{
	internal static class VisualStates
	{
		#region GroupCommon

		/// <summary>
		/// Common state group.
		/// </summary>
		public const string GroupCommon = "CommonStates";

		/// <summary>
		/// Normal state of the Common state group.
		/// </summary>
		public const string StateNormal = "Normal";

		/// <summary>
		/// Normal state of the Common state group.
		/// </summary>
		public const string StateReadOnly = "ReadOnly";

		/// <summary>
		/// MouseOver state of the Common state group.
		/// </summary>
		public const string StateMouseOver = "MouseOver";

		/// <summary>
		/// Pressed state of the Common state group.
		/// </summary>
		public const string StatePressed = "Pressed";

		/// <summary>
		/// Disabled state of the Common state group.
		/// </summary>
		public const string StateDisabled = "Disabled";

		#endregion GroupCommon

		#region GroupFocus

		/// <summary>
		/// Focus state group.
		/// </summary>
		public const string GroupFocus = "FocusStates";

		/// <summary>
		/// Unfocused state of the Focus state group.
		/// </summary>
		public const string StateUnfocused = "Unfocused";

		/// <summary>
		/// Focused state of the Focus state group.
		/// </summary>
		public const string StateFocused = "Focused";

		#endregion GroupFocus

		#region GroupSelection

		/// <summary>
		/// Selection state group.
		/// </summary>
		public const string GroupSelection = "SelectionStates";

		/// <summary>
		/// Selected state of the Selection state group.
		/// </summary>
		public const string StateSelected = "Selected";

		/// <summary>
		/// Unselected state of the Selection state group.
		/// </summary>
		public const string StateUnselected = "Unselected";

		/// <summary>
		/// Selected inactive state of the Selection state group.
		/// </summary>
		public const string StateSelectedInactive = "SelectedInactive";

		#endregion GroupSelection

		#region GroupExpansion

		/// <summary>
		/// Expansion state group.
		/// </summary>
		public const string GroupExpansion = "ExpansionStates";

		/// <summary>
		/// Expanded state of the Expansion state group.
		/// </summary>
		public const string StateExpanded = "Expanded";

		/// <summary>
		/// Collapsed state of the Expansion state group.
		/// </summary>
		public const string StateCollapsed = "Collapsed";

		#endregion GroupExpansion

		#region GroupPopup

		/// <summary>
		/// Popup state group.
		/// </summary>
		public const string GroupPopup = "PopupStates";

		/// <summary>
		/// Opened state of the Popup state group.
		/// </summary>
		public const string StatePopupOpened = "PopupOpened";

		/// <summary>
		/// Closed state of the Popup state group.
		/// </summary>
		public const string StatePopupClosed = "PopupClosed";

		#endregion

		#region GroupValidation

		/// <summary>
		/// ValidationStates state group.
		/// </summary>
		public const string GroupValidation = "ValidationStates";

		/// <summary>
		/// The valid state for the ValidationStates group.
		/// </summary>
		public const string StateValid = "Valid";

		/// <summary>
		/// Invalid, focused state for the ValidationStates group.
		/// </summary>
		public const string StateInvalidFocused = "InvalidFocused";

		/// <summary>
		/// Invalid, unfocused state for the ValidationStates group.
		/// </summary>
		public const string StateInvalidUnfocused = "InvalidUnfocused";

		#endregion

		#region GroupExpandDirection

		/// <summary>
		/// ExpandDirection state group.
		/// </summary>
		public const string GroupExpandDirection = "ExpandDirectionStates";

		/// <summary>
		/// Down expand direction state of ExpandDirection state group.
		/// </summary>
		public const string StateExpandDown = "ExpandDown";

		/// <summary>
		/// Up expand direction state of ExpandDirection state group.
		/// </summary>
		public const string StateExpandUp = "ExpandUp";

		/// <summary>
		/// Left expand direction state of ExpandDirection state group.
		/// </summary>
		public const string StateExpandLeft = "ExpandLeft";

		/// <summary>
		/// Right expand direction state of ExpandDirection state group.
		/// </summary>
		public const string StateExpandRight = "ExpandRight";

		#endregion

		#region GroupHasItems

		/// <summary>
		/// HasItems state group.
		/// </summary>
		public const string GroupHasItems = "HasItemsStates";

		/// <summary>
		/// HasItems state of the HasItems state group.
		/// </summary>
		public const string StateHasItems = "HasItems";

		/// <summary>
		/// NoItems state of the HasItems state group.
		/// </summary>
		public const string StateNoItems = "NoItems";

		#endregion GroupHasItems

		#region GroupIncrease

		/// <summary>
		/// Increment state group.
		/// </summary>
		public const string GroupIncrease = "IncreaseStates";

		/// <summary>
		/// State enabled for increment group.
		/// </summary>
		public const string StateIncreaseEnabled = "IncreaseEnabled";

		/// <summary>
		/// State disabled for increment group.
		/// </summary>
		public const string StateIncreaseDisabled = "IncreaseDisabled";

		#endregion GroupIncrease

		#region GroupDecrease

		/// <summary>
		/// Decrement state group.
		/// </summary>
		public const string GroupDecrease = "DecreaseStates";

		/// <summary>
		/// State enabled for decrement group.
		/// </summary>
		public const string StateDecreaseEnabled = "DecreaseEnabled";

		/// <summary>
		/// State disabled for decrement group.
		/// </summary>
		public const string StateDecreaseDisabled = "DecreaseDisabled";

		#endregion GroupDecrease

		#region GroupIteractionMode

		/// <summary>
		/// InteractionMode state group.
		/// </summary>
		public const string GroupInteractionMode = "InteractionModeStates";

		/// <summary>
		/// Edit of the DisplayMode state group.
		/// </summary>
		public const string StateEdit = "Edit";

		/// <summary>
		/// Display of the DisplayMode state group.
		/// </summary>
		public const string StateDisplay = "Display";

		#endregion GroupIteractionMode

		#region GroupLocked

		/// <summary>
		/// DisplayMode state group.
		/// </summary>
		public const string GroupLocked = "LockedStates";

		/// <summary>
		/// Edit of the DisplayMode state group.
		/// </summary>
		public const string StateLocked = "Locked";

		/// <summary>
		/// Display of the DisplayMode state group.
		/// </summary>
		public const string StateUnlocked = "Unlocked";

		#endregion GroupLocked

		#region GroupActive

		/// <summary>
		/// Active state.
		/// </summary>
		public const string StateActive = "Active";

		/// <summary>
		/// Inactive state.
		/// </summary>
		public const string StateInactive = "Inactive";

		/// <summary>
		/// Active state group.
		/// </summary>
		public const string GroupActive = "ActiveStates";

		#endregion GroupActive

		#region GroupWatermark

		/// <summary>
		/// Non-watermarked state.
		/// </summary>
		public const string StateUnwatermarked = "Unwatermarked";

		/// <summary>
		/// Watermarked state.
		/// </summary>
		public const string StateWatermarked = "Watermarked";

		/// <summary>
		/// Watermark state group.
		/// </summary>
		public const string GroupWatermark = "WatermarkStates";

		#endregion GroupWatermark

		#region GroupCalendarButtonFocus

		/// <summary>
		/// Unfocused state for Calendar Buttons.
		/// </summary>
		public const string StateCalendarButtonUnfocused = "CalendarButtonUnfocused";

		/// <summary>
		/// Focused state for Calendar Buttons.
		/// </summary>
		public const string StateCalendarButtonFocused = "CalendarButtonFocused";

		/// <summary>
		/// CalendarButtons Focus state group.
		/// </summary>
		public const string GroupCalendarButtonFocus = "CalendarButtonFocusStates";

		#endregion GroupCalendarButtonFocus

		#region GroupBusyStatus

		/// <summary>
		/// Busy state for BusyIndicator.
		/// </summary>
		public const string StateBusy = "Busy";

		/// <summary>
		/// Idle state for BusyIndicator.
		/// </summary>
		public const string StateIdle = "Idle";

		/// <summary>
		/// Busyness group name.
		/// </summary>
		public const string GroupBusyStatus = "BusyStatusStates";

		#endregion

		#region GroupVisibility

		/// <summary>
		/// Visible state name for BusyIndicator.
		/// </summary>
		public const string StateVisible = "Visible";

		/// <summary>
		/// Hidden state name for BusyIndicator.
		/// </summary>
		public const string StateHidden = "Hidden";

		/// <summary>
		/// BusyDisplay group.
		/// </summary>
		public const string GroupVisibility = "VisibilityStates";

		#endregion

		/// <summary>
		/// Use VisualStateManager to change the visual state of the control.
		/// </summary>
		/// <param name="control">
		/// Control whose visual state is being changed.
		/// </param>
		/// <param name="useTransitions">
		/// A value indicating whether to use transitions when updating the
		/// visual state, or to snap directly to the new visual state.
		/// </param>
		/// <param name="stateNames">
		/// Ordered list of state names and fallback states to transition into.
		/// Only the first state to be found will be used.
		/// </param>
		public static void GoToState(Control control, bool useTransitions, params string[] stateNames)
		{
			Debug.Assert(control != null, "control should not be null!");
			Debug.Assert(stateNames != null, "stateNames should not be null!");
			Debug.Assert(stateNames.Length > 0, "stateNames should not be empty!");

			foreach (string name in stateNames)
			{
				if (VisualStateManager.GoToState(control, name, useTransitions))
				{
					break;
				}
			}
		}

		/// <summary>
		/// Gets the implementation root of the Control.
		/// </summary>
		/// <param name="dependencyObject">The DependencyObject.</param>
		/// <remarks>
		/// Implements Silverlight's corresponding internal property on Control.
		/// </remarks>
		/// <returns>Returns the implementation root or null.</returns>
		public static FrameworkElement GetImplementationRoot(DependencyObject dependencyObject)
		{
			Debug.Assert(dependencyObject != null, "DependencyObject should not be null.");
			return (1 == VisualTreeHelper.GetChildrenCount(dependencyObject))
				       ? VisualTreeHelper.GetChild(dependencyObject, 0) as FrameworkElement
				       : null;
		}

		/// <summary>
		/// This method tries to get the named VisualStateGroup for the 
		/// dependency object. The provided object's ImplementationRoot will be 
		/// looked up in this call.
		/// </summary>
		/// <param name="dependencyObject">The dependency object.</param>
		/// <param name="groupName">The visual state group's name.</param>
		/// <returns>Returns null or the VisualStateGroup object.</returns>
		public static VisualStateGroup TryGetVisualStateGroup(DependencyObject dependencyObject, string groupName)
		{
			FrameworkElement root = GetImplementationRoot(dependencyObject);
			if (root == null)
			{
				return null;
			}

			return VisualStateManager.GetVisualStateGroups(root)
			                         .OfType<VisualStateGroup>()
			                         .Where(group => string.CompareOrdinal(groupName, group.Name) == 0)
			                         .FirstOrDefault();
		}
	}
}